#include <QLinearGradient>
#include <QMouseEvent>
#include <QPainter>
#include <QTimer>
#include "slideswitch.h"

#define PADDING_LEFT_RIGHT 2  ///< 左右内间距
#define PADDING_TOP_BOTTOM 2  ///< 上下内间距

SlideSwitch::SlideSwitch(QWidget *parent) :
    QWidget(parent),
    m_isAnimated(true),
    m_isShowTip(true),
    m_isPressed(false),
    m_isCanChecked(false),
    m_isChecked(false),
    m_bgColor(QColor(220,223,230)),
    m_sliderColor(QColor(255, 255, 255)),
    m_tipLightColor(QColor(255, 255, 255)),
    m_tipLightCheckColor(QColor(255, 255, 255)),
    m_tipLightCurrentColor(m_tipLightColor),
    m_radius(3.0),
    m_interval(10),
    m_timer(new QTimer(this)),
    m_sliderX(2),
    m_step(5)
{
    connect(m_timer, &QTimer::timeout, this, &SlideSwitch::animateTimer);

    setBaseSize(50, 30);  // 设置默认大小
}


SlideSwitch::~SlideSwitch()
{
}


void SlideSwitch::setChecked(bool checked)
{
    if (m_isAnimated) {
        if (m_isChecked) {
            m_isChecked = checked;
            m_timer->start(m_interval);
        }
        else {
            m_isChecked = checked;
            m_timer->start(m_interval);

        }
    }
    else {
        if (m_isChecked) {
            m_isChecked            = checked;
            m_sliderX              = PADDING_LEFT_RIGHT;
            m_tipLightCurrentColor = m_tipLightColor;
        }
        else {
            m_isChecked            = checked;
            m_sliderX              = width() / 2 + PADDING_LEFT_RIGHT;
            m_tipLightCurrentColor = m_tipLightCheckColor;
        }
    }
    update();
}


void SlideSwitch::setShowTip(bool showTip)
{
    m_isShowTip = showTip;
    update();
}


void SlideSwitch::setBgColor(const QColor &color)
{
    m_bgColor = color;
    update();
}


void SlideSwitch::setSliderColor(const QColor &color)
{
    m_sliderColor = color;
    update();
}


void SlideSwitch::setTipLightColor(const QColor &color)
{
    m_tipLightColor = color;
    update();
}


void SlideSwitch::setTipLightCheckColor(const QColor &color)
{
    m_tipLightCheckColor = color;
    update();
}


void SlideSwitch::setRadius(qreal radius)
{
    m_radius = radius;
    update();
}


void SlideSwitch::setAnimated(bool animated)
{
    m_isAnimated = animated;
}


void SlideSwitch::setAnimationInterval(int interval)
{
    m_interval = interval;
}


void SlideSwitch::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    drawBg(&painter);
    drawSlider(&painter);
    drawTipLight(&painter);
}


void SlideSwitch::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_isPressed    = true;
        m_isCanChecked = true;
    }

    QWidget::mousePressEvent(event);
}


void SlideSwitch::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_isPressed) return;

    QRect rect = this->rect();
    rect.adjust(PADDING_LEFT_RIGHT, PADDING_TOP_BOTTOM, -PADDING_LEFT_RIGHT, -PADDING_TOP_BOTTOM);
    m_isCanChecked = rect.contains(event->pos());
}


void SlideSwitch::mouseReleaseEvent(QMouseEvent *event)
{
    m_isPressed = false;

    if (event->button() == Qt::LeftButton && m_isCanChecked)
    {
        if (m_isAnimated) {
            if (m_isChecked) {
                m_isChecked = false;
                m_timer->start(m_interval);
            }
            else {
                m_isChecked = true;
                m_timer->start(m_interval);
            }
        }
        else {
            if (m_isChecked) {
                m_isChecked            = false;
                m_sliderX              = PADDING_LEFT_RIGHT;
                m_tipLightCurrentColor = m_tipLightColor;
            }
            else {
                m_isChecked            = true;
                m_sliderX              = width() / 2 + PADDING_LEFT_RIGHT;
                m_tipLightCurrentColor = m_tipLightCheckColor;
            }

            update();
        }

        emit checkedChanged(m_isChecked);
    }

    QWidget::mouseReleaseEvent(event);
}


void SlideSwitch::animateTimer()
{
    if (m_isChecked) {
        if (m_sliderX < width() / 2 + PADDING_LEFT_RIGHT) {
            m_sliderX += m_step;
        }
        else {
            m_sliderX              = width() / 2 + PADDING_LEFT_RIGHT;
            m_tipLightCurrentColor = m_tipLightCheckColor;
            m_timer->stop();
        }
    }
    else {
        if (m_sliderX > PADDING_LEFT_RIGHT) {
            m_sliderX -= m_step;
        }
        else {
            m_sliderX              = PADDING_LEFT_RIGHT;
            m_tipLightCurrentColor = m_tipLightColor;
            m_timer->stop();
        }
    }

    update();
}


void SlideSwitch::drawBg(QPainter *painter)
{
    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setBrush(m_bgColor);

    painter->drawRoundedRect(rect(), m_radius, m_radius);

    painter->restore();
}


void SlideSwitch::drawSlider(QPainter *painter)
{
    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setBrush(m_sliderColor);

    qreal width  = this->width() / 2.0 - PADDING_LEFT_RIGHT * 2.0;
    qreal height = this->height() - PADDING_TOP_BOTTOM * 2.0;

    painter->drawRoundedRect(m_sliderX, PADDING_TOP_BOTTOM, (int)width, (int)height, m_radius, m_radius);

    painter->restore();
}


void SlideSwitch::drawTipLight(QPainter *painter)
{
    if (!m_isShowTip) return;

    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setBrush(m_tipLightCurrentColor);

    qreal width  = this->height() / 4.0 - PADDING_LEFT_RIGHT;
    qreal height = width;

    qreal xStart  = this->width() / 3.0 - width / 2 - PADDING_LEFT_RIGHT;
    qreal xEnd    = this->width() / 3.0 * 2 - width / 2 - PADDING_LEFT_RIGHT;
    qreal len     = xEnd - xStart;
    qreal percent = len / (this->width() / 2.0 - PADDING_LEFT_RIGHT * 2);

    qreal x = xStart + m_sliderX * percent;
    qreal y = this->height() / 2.0 - height / 2.0;
    painter->drawEllipse((int)x, (int)y, (int)width, (int)height);

    painter->restore();
}
